﻿var cvis = {
    _children: [],
    _size: null,
    _ctx: null,
    isVisible:true,
    _animations:[],
    //{canvas:
    // size:
    // interval
    //}
    _event:{handled :true, pos:[0,0]},
    start: function (config) {
        this._ctx = config.canvas.getContext("2d");
        this._size = config.size;
        this._interval = config.interval;
        var interval = this._interval;
        window.setInterval(function () {
            cvis_timer_tick(interval);
        }, this._interval);
        
        $(document).on('click', function (event) {
            cvis.event_click([event.pageX, event.pageY]);
        });
    },
    event_click:function(pos){
        this._event.handled = false;
        this._event.pos[0] = pos[0];
        this._event.pos[1] = pos[1];
    },
    render: function (ctx, delta) {
        //console.log('cvis.render:' + delta);
        ctx.clearRect(0, 0, this._size.w, this._size.h);
        if (this.isVisible) {
            for (var index = 0; index < this._children.length; index++) {
                if (this._children[index].isVisible) {
                    this._children[index].render(ctx, delta, [0, 0]);
                }
            }
        }
    },
    update: function (delta) {
        //console.log('cvis.update:' + delta);
        for (var index = 0; index < this._animations.length; index++) {
            this._animations[index].update(delta);
        }

        // remove completed animation
        for (var index = 0; index < this._animations.length;) {
            if (this._animations[index].isCompleted()) {
                this._animations.splice(index, 1);
            } else {
                index++;
            }
        }

        for (var index = 0; index < this._children.length; index++) {
            if (this._children[index].isVisible) {
                this._children[index].update(this._event, delta, [0,0]);
            }
        }
    },
    loop: function (delta) {
        this.update(delta);
        this.render(this._ctx, delta);
    },
    addNode: function (node) {
        this._children.push(node);
    },
    // 添加动画
    addAnimation: function (animation) {
        this._animations.push(animation);
    }
};

function cvis_timer_tick(delta) {
    cvis.loop(delta);
}

//option.tex2d:string
//option.pos :array
function cvisNode(option) {
    this.option = option;
    this._children = [];
    this._pivot = [0, 0];
    this._tex2dUrl = null;
    this._animations = [];
    if (option.tex2d) {
        this._tex2dUrl = option.tex2d;
    }
    this._tex2d = null;
    this._size = null;
    this._pos = [0, 0];
    if (option.pos) {
        this._pos = option.pos;
    }
    this._isInited = false;
    this.isVisible = true;
    this.init = function () {
        if (this._tex2dUrl) {
            this._tex2d = new Image();
            this._tex2d.src = this._tex2dUrl;
        }
        this.onInit();
        this._isInited = true;
    }
    this.onInit = function () {

    }
    this.addNode = function (node) {
        this._children.push(node);
    }
    this.update = function (event, delta, originalPos) {
        if (this._isInited == false) {
            this.init();
        } else {
            if (this._size == null && this._tex2d != null && this._tex2d.width > 0 && this._tex2d.height > 0) {
                this._size = [this._tex2d.width, this._tex2d.height];
            }

            for (var index = 0; index < this._animations.length; index++) {
                this._animations[index].update(delta);
            }

            // remove completed animation
            for (var index = 0; index < this._animations.length;) {
                if (this._animations[index].isCompleted()) {
                    this._animations.splice(index, 1);
                } else {
                    index++;
                }
            }

            this.onUpdate(event, delta, originalPos);
            for (var index = 0; index < this._children.length; index++) {
                this._children[index].update(event, delta, [originalPos[0] + this._pos[0], originalPos[1] + this._pos[1]]);
            }
        }
    }
    this.onUpdate = function (event, delta, originalPos) {

    }

    //
    //
    // originalPos:array 起点
    this.render = function (ctx, delta, originalPos) {
        this.onRender(ctx, delta, originalPos);
        for (var index = 0; index < this._children.length; index++) {
            if (this._children[index].isVisible) {
                this._children[index].render(ctx, delta, [originalPos[0] + this._pos[0], originalPos[1] + this._pos[1]]);
            }
        }
    }
    this.onRender = function (ctx, delta, originalPos) {
        if (this._tex2d != null && this._tex2d.width > 0 && this._tex2d.height > 0) {
            ctx.drawImage(this._tex2d,
                originalPos[0] + this._pos[0] - this._size[0] * this._pivot[0],
                originalPos[1] + this._pos[1] - this._size[1] * this._pivot[1]);
        }
    }

    //api
    this.setPivot = function (pivot) {
        this._pivot = pivot;
    }
    this.setPos = function (pos) {
        this._pos = pos;
    }
    this.getNodeCount = function () {
        return this._children.length;
    }
    this.getNodeAt = function (index) {
        return this._children[index];
    }
    // 添加动画
    this.addAnimation = function (animation) {
        this._animations.push(animation);
    }
}

//option.text
//option.fontSize
//option.color
//option.pos
function cvisLabel(option) {
    cvisNode.call(this, option);
    this._fontSize = option.fontSize;
    this._text = option.text;
    this._color = option.color;
    this.onRender = function (ctx, delta, originalPos) {
        ctx.textBaseline = 'top';
        ctx.font = this._fontSize + 'px Arial';
        ctx.fillStyle = this._color;
        var length = ctx.measureText(this._text);
        ctx.fillText(this._text, originalPos[0] + this._pos[0] - this._pivot[0] * length.width, originalPos[1] + this._pos[1] - this._pivot[1] * this._fontSize);
    }
}

//option.tex2d
//option.tex2dSel
function cvisToggleButton(option) {
    cvisNode.call(this, option);
    this._eventList = [];
    this.isChecked = false;
    this._tex2dSel = null;
    this._tex2dSelUrl = option.tex2dSel;
    this.onInit = function () {
        if (this._tex2dSelUrl) {
            this._tex2dSel = new Image();
            this._tex2dSel.src = this._tex2dSelUrl;
        }
    }
    this.onRender = function (ctx, delta, originalPos) {
        if (this.isChecked) {
            if (this._tex2dSel != null && this._tex2dSel.width > 0 && this._tex2dSel.height > 0) {
                ctx.drawImage(this._tex2dSel,
                    originalPos[0] + this._pos[0] - this._size[0] * this._pivot[0],
                    originalPos[1] + this._pos[1] - this._size[1] * this._pivot[1]);
            }
        } else {
            if (this._tex2d != null && this._tex2d.width > 0 && this._tex2d.height > 0) {
                ctx.drawImage(this._tex2d,
                    originalPos[0] + this._pos[0] - this._size[0] * this._pivot[0],
                    originalPos[1] + this._pos[1] - this._size[1] * this._pivot[1]);
            }
        }
    }
    this.onUpdate = function (event, delta, originalPos) {
        if (this._size == null && this._tex2d != null && this._tex2d.width > 0 && this._tex2d.height > 0) {
            this._size = [this._tex2d.width, this._tex2d.height];
        }
        if(event.handled == false){
            var absPos = [originalPos[0] + this._pos[0], originalPos[1] + this._pos[1]];
            if (event.pos[0] > absPos[0] && event.pos[0] < absPos[0] + this._size[0]
                && event.pos[1] > absPos[1] && event.pos[1] < absPos[1] + this._size[1]) {
                event.handled = true;
                this.isChecked = !this.isChecked;
                this._eventList[0].callback();
            }
        }
    }
    this.on = function (event, callback) {
        this._eventList.push({ name: 'event', callback: callback });
    }
}

//option.number
function cvisNumLabel(option) {
    cvisNode.call(this, option);
    this._fontSize = option.fontSize;
    this._number = option.number;
    this._color = option.color;
    this.onUpdate = function (delta) {

    }
    this.onRender = function (ctx, delta, originalPos) {
        ctx.textBaseline = 'top';
        ctx.font = this._fontSize + 'px Arial';
        ctx.fillStyle = this._color;
        var length = ctx.measureText(this._text);
        ctx.fillText(this._text, originalPos[0] + this._pos[0] - this._pivot[0] * length.width, originalPos[1] + this._pos[1] - this._pivot[1] * this._fontSize);
    }
}

function cvisSequence(animations) {
    this._animations = animations;
    this._isCompleted = false;
    this.isCompleted = function () {
        return this._isCompleted;
    }
    this.update = function (delta) {
        for (var index = 0; index < this._animations.length; index++) {
            if (!this._animations[index]._isCompleted) {
                this._animations[index].update(delta);
                break;
            }
        }
        for (var index = 0; index < this._animations.length; index++) {
            if (!this._animations[index]._isCompleted) {
                this._isCompleted = false;
                return;
            }
        }
        this._isCompleted = true;
    }
    this.reset = function () {
        for (var index = 0; index < this._animations.length; index++) {
            this._animations[index].reset();
        }
        this._isCompleted = false;
    }
}
function cvisFunc(callback, data) {
    this._callback = callback;
    this._data = data;
    this._isCompleted = false;
    this.isCompleted = function () {
        return this._isCompleted;
    }
    this.update = function (delta) {
        this._callback(data);
        this._isCompleted = true;
    }
    this.reset = function () {
        this._isCompleted = false;
    }
}
function cvisWait(duration) {
    this._life = 0;
    this._duration = duration;
    this._isCompleted = false;
    this.isCompleted = function () {
        return this._isCompleted;
    }
    this.update = function (delta) {
        if (this._isCompleted) {
            return;
        }
        this._life += delta;
        if (this._life >= this._duration) {
            this._isCompleted = true;
        }
    }
    this.reset = function(){
        this._life = 0;
        this._isCompleted = false;
    }
}
function cvisForever(animation) {
    this._animation = animation;
    this._isCompleted = false;
    this.isCompleted = function () {
        return this._isCompleted;
    }
    this.update = function (delta) {
        this._animation.update(delta);
        if (this._animation._isCompleted) {
            this._animation.reset();
        }
    }
}